﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using IWshRuntimeLibrary;
using LaunchMeNot.Core;
using LaunchMeNot.Core.Loggers;

namespace LaunchMeNot.DAL
{
    /// <summary>
    /// Stores shortcuts as .lnk files in a folder.
    /// </summary>
    public class DirectoryStore : IEntryStore
    {
        private ILogProvider _logger;

        /// <summary>
        /// Gets or sets path of the directory used to store entries.
        /// </summary>
        /// <value>The path of the file directory to store entries.</value>
        public string DirectoryPath { get; set; }

        /// <summary>
        /// Gets or sets the type of entries in this store.
        /// </summary>
        /// <value>The type of entries in this store.</value>
        public StartupEntryType EntryType { get; private set; }

        /// <summary>
        /// Initializes a new <see cref="directoryPath"/>.
        /// </summary>
        /// <param name="entryType">Type of the entries in this store.</param>
        public DirectoryStore(StartupEntryType entryType)
        {
            if(entryType != StartupEntryType.AllUsersStartup && entryType != StartupEntryType.CurrentUserStartup)
                    throw new ArgumentException("Only start menu startup entries are supported by this store.");
            this.EntryType = entryType;
            this.DirectoryPath = LaunchMeNotBLL.GetPath(entryType);
            _logger = new ConsoleLogger();
        }

        /// <summary>
        /// Initializes a new <see cref="directoryPath"/>.
        /// </summary>
        /// <param name="directoryPath">The directory in which to store entries.</param>
        public DirectoryStore(string directoryPath)
        {
            this.DirectoryPath = directoryPath;
            _logger = new ConsoleLogger();
        }

        /// <summary>
        /// Creates a new shortcut.
        /// </summary>
        /// <param name="entry">The entry.</param>
        public void AddStartupEntry(IStartupEntry entry)
        {
            AddStartupEntries(new[] { entry });
        }

        /// <summary>
        /// Adds multiple new shortcuts.
        /// </summary>
        /// <param name="entries">The entries.</param>
        public void AddStartupEntries(IEnumerable<IStartupEntry> entries) {
            var shell = new WshShell();
            ShellShortcut firstExistingEntry = (ShellShortcut)entries.FirstOrDefault(e =>
            {
                string shortcutPath = Path.Combine(DirectoryPath, ((ShellShortcut)e).ShortcutFilename);
                return System.IO.File.Exists(shortcutPath);
            });
            if(firstExistingEntry != null)
                throw new LaunchMeNotException(650, I18nUtils.GetString("Errors", "ShortcutNameExistsFmt", firstExistingEntry.Name));
            
            foreach (IStartupEntry entry in entries) {
                ShellShortcut shellShortcut = entry as ShellShortcut;
                if (shellShortcut == null)
                    throw new Exception("Only ShellShortcuts can be stored in a directory");
                string shortcutPath = Path.Combine(DirectoryPath, shellShortcut.ShortcutFilename);
                IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath); // ...\Start Menu\MyProg.lnk
                shortcut.TargetPath = shellShortcut.Path; // C:\MyProg.exe
                shortcut.Arguments = shellShortcut.Arguments;
                shortcut.Description = shellShortcut.Description; // MyProg
                shortcut.Save();
            }
        }

        /// <summary>
        /// Edits a startup entry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        public void EditStartupEntry(IStartupEntry entry) {
            ShellShortcut realEntry = entry as ShellShortcut;
            if (realEntry == null)
                throw new ArgumentException("Only Shell Shortcut Entries (.lnk files) can be stored here.");
            string shortcutPath = Path.Combine(DirectoryPath, realEntry.ShortcutFilename);
            if (!string.IsNullOrEmpty(realEntry.OriginalName) && realEntry.OriginalName != realEntry.ShortcutFilename) {
                //delete the original if the name has changed
                if (System.IO.File.Exists(shortcutPath))
                    throw new LaunchMeNotException(650, I18nUtils.GetString("Errors", "ShortcutNameExistsFmt", shortcutPath));
                string originalPath = Path.Combine(DirectoryPath, realEntry.OriginalName);
                System.IO.File.Delete(originalPath);
            }

            
            var shell = new WshShell();
            IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath); // ...\Start Menu\MyProg.lnk
            shortcut.TargetPath = realEntry.Path; // C:\MyProg.exe
            shortcut.Arguments = realEntry.Arguments;
            shortcut.Description = realEntry.Description; // MyProg
            shortcut.Save();
        }

        /// <summary>
        /// Deletes a shortcut.
        /// </summary>
        /// <param name="entry">The entry.</param>
        public void DeleteStartupEntry(IStartupEntry entry) {
            DeleteStartupEntries(new[] { entry });
        }

        /// <summary>
        /// Deletes multiple startup entries.
        /// </summary>
        /// <param name="entries">The entries.</param>
        public void DeleteStartupEntries(IEnumerable<IStartupEntry> entries) {
            foreach (ShellShortcut entry in entries) {
                ShellShortcut shellShortcut = entry as ShellShortcut;
                if(shellShortcut == null)
                    throw new Exception("Only ShellShortcuts can be stored in a directory");
                string shortcutPath = Path.Combine(DirectoryPath, shellShortcut.ShortcutFilename);
                System.IO.File.Delete(shortcutPath);
            }
        }

        /// <summary>
        /// Gets a list of all shortcuts in the directory.
        /// </summary>
        /// <returns>All startup shortcuts in the directory.</returns>
        public IList<IStartupEntry> GetStartupEntries() {
            string[] shortcutPaths = Directory.GetFiles(DirectoryPath, "*.lnk");
            var shell = new WshShell();
            var entries = shortcutPaths.Select(f =>
            {
                return new ShellShortcut(f) { EntryType = this.EntryType };
            }).Cast<IStartupEntry>().ToList();
            return entries;
        }
    }
}
